`timescale 1ns / 1ps
/******************************************************************************
*                                                                             *
* UTICA softcore v0.1                                                         *
*                                                                             *
* Copyright (c) 2012 Andrew D. Zonenberg                                      *
* All rights reserved.                                                        *
*                                                                             *
* Redistribution and use in source and binary forms, with or without modifi-  *
* cation, are permitted provided that the following conditions are met:       *
*                                                                             *
*    * Redistributions of source code must retain the above copyright notice  *
*      this list of conditions and the following disclaimer.                  *
*                                                                             *
*    * Redistributions in binary form must reproduce the above copyright      *
*      notice, this list of conditions and the following disclaimer in the    *
*      documentation and/or other materials provided with the distribution.   *
*                                                                             *
*    * Neither the name of the author nor the names of any contributors may be*
*      used to endorse or promote products derived from this software without *
*      specific prior written permission.                                     *
*                                                                             *
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS "AS IS" AND ANY EXPRESS OR IMPLIED *
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF        *
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN     *
* NO EVENT SHALL THE AUTHORS BE HELD LIABLE FOR ANY DIRECT, INDIRECT,         *
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT    *
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,   *
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY       *
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT         *
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF    *
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.           *
*                                                                             *
******************************************************************************/

/**
	@file UticaCPUPostWritebackStage.v
	@author Andrew D. Zonenberg
	@brief All processing that happens after writeback.
	
	For now this is just long-running operations like multiply or divide.
 */
module UticaCPUPostWritebackStage(
	clk,
	multout_s, multout_u,
	div_done, div_active, div_quot, div_rem,
	mdu_lo, mdu_hi,
	writeback_mult, writeback_multu,
	postwb2_mult, postwb2_multu
    );

	////////////////////////////////////////////////////////////////////////////////////////////////
	// IO declarations

	input wire clk;
	
	input wire[63:0] multout_s;
	input wire[63:0] multout_u;
	
	input wire div_done;
	input wire div_active;
	input wire[31:0] div_quot;
	input wire[31:0] div_rem;
	
	input wire writeback_mult;
	input wire writeback_multu;
	
	reg postwb1_mult = 0;
	output reg postwb2_mult = 0;
	
	reg postwb1_multu = 0;
	output reg postwb2_multu = 0;
	
	output reg[31:0] mdu_lo = 0;
	output reg[31:0] mdu_hi = 0;

	////////////////////////////////////////////////////////////////////////////////////////////////
	// Needs to execute regardless of hold state so that we can get the result into $lo / $hi
	
	always @(posedge clk) begin
		postwb1_mult <= writeback_mult;
		postwb2_mult <= postwb1_mult;
		
		postwb1_multu <= writeback_multu;
		postwb2_multu <= postwb1_multu;
		
		if(postwb2_mult) begin
			//TODO: trigger exception if doing signed multiply and it overflows
			mdu_lo <= multout_s[31:0];
			mdu_hi <= multout_s[63:32];
		end
		
		if(postwb2_multu) begin
			mdu_lo <= multout_u[31:0];
			mdu_hi <= multout_u[63:32];
		end
		
		//Need to check div_active, otherwise division might have been aborted
		if(div_done && div_active) begin
			mdu_lo <= div_quot;
			mdu_hi <= div_rem;
		end
		
	end

endmodule
